<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>async和await</title>
  </head>
  <body></body>
  <script>
    // 1. async 函数和普通函数的声明方式

    // 独立函数声明
    function fn() {}
    async function fo() {}

    //  属性值声明
    const obj = {
      fn: function () {},
      fo: async function () {},
    };

    // 箭头函数声明
    const fnArrow = () => {};
    const foArrow = async () => {};

    // 2. async 函数和普通函数返回值的区别

    function fnWithRet() {
      var x = 1;
      return x + 1;
    }
    async function foWithRet() {
      var x = 1;
      return x + 1;
    }

    // 普通函数的返回值：
    // 默认返回值是 undefined，可以使用 return 关键字指定返回值
    console.log(fnWithRet()); // 2

    // async 函数的返回值:
    // 总是返回一个 Promise 对象，并且具体的状态由返回值的类型决定，具体判定标准和 then 方法回调函数返回值类型判定标准相同
    console.log(foWithRet()); // Promise {<fulfilled>: 2}

    // 3. async 函数中 await 的作用
    // await 操作符用于等待一个 Promise 对象, 将成功状态执行结果作为表达式返回值
    // 它只能在 async 函数内部使用。

    function delay(time, value) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(value);
        }, time);
      });
    }
    async function bar() {
      let value = await delay(1000, "x");
      console.log("after 1s", value); // x
    }
    bar();

    // await 如果后面不是一个 Promsie 对象，会将该值作为 Promise.reslove() 参数（即自动转换为成功状态执行结果），将计算的值作为表达式返回值
    async function baz() {
      let value = await "x";
      console.log("hello world", value); // x
    }
    baz();

    // 4. async 函数内部的错误捕获
    // 可以在函数返回值中使用 catch 进行捕获
    async function fnWithError1() {
      throw new Error("错误");
    }
    fnWithError1().catch((error) => {
      console.log(error);
    });

    // 可以在函数内部使用 try...catch... 捕获
    async function fnWithError2() {
      try {
        throw new Error("错误");
      } catch (error) {
        console.log(error);
      }
    }
    fnWithError1();

    // 针对 await 抛出的错误，可以由对应的 Promise 对象自行捕获
    async function fnWithError3() {
      await Promise.reject("错误").catch((error) => {
        console.log(error);
      });
    }
    fnWithError3();
  </script>
</html>
